from waitress import serve
from flask import Flask
# from flask import Blueprint
from flask import render_template, redirect, url_for, request, jsonify, g
import celeryAsrTask
import celeryClipTask
from celery import Celery
from celery.result import AsyncResult
import os
import pubfunc
import returnJson
import auth
import dbExcute
import dbClipExecute
import dbstruct
import threading
import monitor_gpus
import json
import redis

subapp = Flask(__name__)
# subapp = Blueprint('subapp', __name__)

logger = pubfunc.getLogger()
broker = os.environ.get('BROKER')
backend = os.environ.get('BACKEND')
SUPLOAD_PATH = os.environ.get('SUPLOAD_PATH')
SUBTITLE_URL = os.environ.get('SUBTASK_URL')
BASEURL = os.environ.get('SBASE_URL')
ISMONITOR = False

celery = Celery("tasks", broker=broker, backend=backend)
# 查询字幕处理任务的资源
@subapp.route('/subtitle/getSubTaskList', methods=['GET', 'POST'])
@auth.require_auth 
def getSubTaskList():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')
    page = request.args.get('page', '1')  
    pagesize = request.args.get('pagesize', '12')  
    if(corpid == '' or corpid == None or userid == '' or userid == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata, totle = dbExcute.getTaskList(corpid, userid, page, pagesize)
    return jsonify(returnJson.success(ndata, tlen=totle))

# 查询处理的日志
@subapp.route('/subtitle/getSubTaskLogs', methods=['GET', 'POST'])
@auth.require_auth 
def getSubTaskLogs():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')
    uuid1 = request.args.get('uuid1', '-1')  

    if(corpid == '' or corpid == None or userid == '' or userid == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata = dbExcute.getTaskLogs(uuid1)
    return jsonify(returnJson.success(ndata, tlen=1))

@subapp.route('/subtitle/getSubtitleTaskInfo', methods=['GET', 'POST'])
@auth.require_auth 
def getSubtitleTaskInfo():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')
    taskid = request.args.get('taskid')
    if(corpid == '' or corpid == None or userid == '' or userid == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 获取任务列表信息
    ndata = dbExcute.getSubtitleTask(corpid, userid, taskid)
    return jsonify(returnJson.success(ndata, tlen=1))

@subapp.route('/subtitle/getSubtitleTaskStatus', methods=['GET', 'POST'])
def getSubtitleTaskStatus():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')  
    taskid = request.args.get('taskid')  
    if(id == '' or id == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata = dbExcute.getSubtitleTaskStatus(corpid, userid, taskid)
    return jsonify(returnJson.success(ndata))

@subapp.route('/subtitle/delSubtitleTask', methods=['GET', 'POST'])
def delSubtitleTask():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')  
    taskid = request.args.get('taskid')  
    if(id == '' or id == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata = dbExcute.delSubtitleTask(corpid, userid, taskid)
    return jsonify(returnJson.success1(None))

# 增加新的字幕处理的任务
@subapp.route('/subtitle/addSubtitleTask', methods=['GET', 'POST'])
def subtitleTask_add():
    try:
        if request.method == 'GET':
            return jsonify(returnJson.error(msg=f"请使用POST方法提交;"))

        data = request.json
        if(data == None):
            return jsonify(returnJson.error(msg="接收前端数据错误"))
        
        videopath = data.get("videopath", "")
        corpid = data.get("corpid", "")
        tname = data.get("tname", pubfunc.getFileName(videopath))
        userid = data.get("uid", "")
        duration = data.get("duration", 0)
        en = data.get("en", "0")
        # 如果isauto的标志为1，则自动进行识别;
        autoflag = data.get("isauto", "0")

        # if not checkAuth(corpid, userid):
        #     return jsonify(returnJson.error(msg="没有操作权限"))

        if videopath == None or videopath == "":
            return jsonify(returnJson.error(msg="没有获取到视频地址")) 
        
        # 视频地址为{SUBTASK_URL}/{tmd5}/
        tmd5 = pubfunc.getMD5(videopath)[:16]
        subtask = dbstruct.getSubTaskDt()
        # 这是视频的上传路径
        subtask["videopath"] = videopath
        # 上传后经过预处理，会生成1080P和360P的两个码流的内容；
        # subtask["videourl"] = f"{SUBTITLE_URL}/{tmd5}/video_360p.mp4"
        # # 先按视频地址生成字幕的地址
        # subtask["subtitleurl"] = f"{SUBTITLE_URL}/{tmd5}/subtitle.srt"
        # subtask["reviewurl"] = f"{SUBTITLE_URL}/{tmd5}/video_360p.mp4"
        subtask["corpid"] = corpid
        subtask["duration"] = int(duration)
        subtask["tmd5"] = tmd5
        subtask["cman"] = userid
        subtask["tname"] = tname
        subtask["en"] = en
        subtask["step"] = 1
        subtask["process"] = 0
        subtask["status"] = 1
        result = celeryAsrTask.asrTask.apply_async(args=[subtask, ])
        celeryID = str(result)
        subtask["uuid1"] = celeryID
    # 保存数据入数据库
        dbExcute.addSubtitleTask(subtask)
        dbExcute.addTaskLog(celeryID, "上传文件完成")
        return jsonify(returnJson.success1("操作成功"))
    except Exception as e:
        dbExcute.addTaskLog(celeryID, f"建立新任务错误[{str(e)}]")
        return jsonify(returnJson.error(f"处理失败,请联系管理员![{str(e)}]"))

# 更新任务的名称
@subapp.route('/subtitle/updateSubtitleTaskTitle', methods=['GET', 'POST'])
def updateSubtitleTaskTitle():

    if request.method == 'GET':
       return jsonify(returnJson.error(msg=f"请使用POST方法提交;"))

    data = request.json
    if(data == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    
    tname = data.get("tname", "")
    taskid = data.get("taskid", "")
    corpid = data.get("corpid", "")
    userid = data.get("uid", "")

    if taskid == None or taskid == "":
        return jsonify(returnJson.error(msg="没有获取到任务编号")) 
    # 保存数据入数据库
    dbExcute.updateSubtitleTaskTitle(corpid, userid, taskid, tname)
    return jsonify(returnJson.success1("操作成功"))

# 更新字幕内容, 这个功能如果upload不是在一台机器上，需要把上专目录挂接到这台机器上，否则会更新不了文件，切记、切记！！！！
@subapp.route('/subtitle/updateSubtitleFile', methods=['GET', 'POST'])
def updateSubtitleFile():

    if request.method == 'GET':
       return jsonify(returnJson.error(msg=f"请使用POST方法提交;"))

    data = request.json
    if(data == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    try: 
        taskid = data.get("taskid", "")
        corpid = data.get("corpid", "")
        userid = data.get("uid", "")
        subtitle = data.get("subtitle", None)

        if taskid == None or taskid == "":
            return jsonify(returnJson.error(msg="没有获取到任务编号")) 
        # 保存数据入数据库
        rdata = dbExcute.getSubtitleTask(corpid, userid, taskid)
        # 如果uuid1与rdata的uuid1数据不一致，则报错
        if(rdata == None):
            dbExcute.addTaskLog(uuid1, f"没有获取到视频信息")
            return jsonify(returnJson.error(msg="没有获取到视频信息")) 

        # 把rdata中的值获取后组合为新的地址
        subpath = f"{os.environ.get('SUBTASK_PATH')}/{rdata.get('tmd5')}/subtitle.srt"
        with open(subpath, "w+", encoding='utf-8') as f:
            json.dump(subtitle, f, ensure_ascii=False, indent=4)
        return jsonify(returnJson.success1("字幕保存成功"))

    except Exception as e:
        return jsonify(returnJson.error(msg=f"请求的数据错误！{str(e)[:100]}"))

# 增加分割视频的任务；(提交包括id和重新生成的字幕内容)
@subapp.route('/subtitle/addClipSubTask', methods=['GET', 'POST'])
def subtitleTask_clip():
    try:
        if request.method == 'GET':
            return jsonify(returnJson.error(msg=f"请使用POST方法提交;"))

        data = request.json
        if(data == None):
            return jsonify(returnJson.error(msg="接收前端数据错误"))
        
        taskid = data.get("id", "")
        corpid = data.get("corpid", "")
        uid = data.get("uid", "")
        uuid1 = data.get("uuid1")
        subdata = data.get("subtitle")
        if(uuid1 == None or uuid1 == ""):
            return jsonify(returnJson.error("剪辑任务请求,数据错误!"))

        dbExcute.addTaskLog(uuid1, f"创建剪辑任务")
        # 获取原始视频的地址
        rdata = dbExcute.getSubtitleTask(corpid, uid, taskid)
        # 如果uuid1与rdata的uuid1数据不一致，则报错
        if(rdata == None or rdata["uuid1"] != uuid1):
            dbExcute.addTaskLog(uuid1, f"没有获取到视频信息")
            return jsonify(returnJson.error(msg="没有获取到视频信息")) 
        
        # 如果当前有任务，则不能够提交新的任务
        if(rdata["process"] != 100):
            dbExcute.addTaskLog(uuid1, f"资源状态异常，请稍候提交")
            return jsonify(returnJson.error(msg="资源状态异常，请稍候提交"))

        # result = celeryClipTask.clipTask.apply_async(args=[rdata, subdata, flag,])
        # celeryID = str(result)
        # dbExcute.addTaskLog(uuid1, f"提交剪切任务[{celeryID}]完成")
        # 把新建的剪切任务保存到subcliptask表中
        clipsubtask = dbstruct.getClipSubTaskDt()
        clipsubtask["corpid"] = corpid
        clipsubtask["subtaskid"] = taskid
        clipsubtask["cman"] = uid
        clipsubtask["tmd5"] = rdata["tmd5"]
        clipsubtask["videopath"] = rdata["videopath"]
        clipsubtask["thumbnail"] = rdata["thumbnail"]
        resolution = data.get("resolution")

        result = celeryClipTask.clipTask.apply_async(args=[clipsubtask, subdata])
        celeryID = str(result)
        dbExcute.addTaskLog(uuid1, f"提交剪切任务[{celeryID}]完成")
        clipsubtask["subtitle"] = str(subdata)[:12000]
        clipsubtask["uuid1"] = celeryID
        clipsubtask["tname"] = celeryID
        dbClipExecute.addClipSubTask(clipsubtask)
        return jsonify(returnJson.success1("任务提交成功"))
    except Exception as e:
        dbExcute.addTaskLog(uuid1, f"建立新任务错误[{str(e)}]")
        return jsonify(returnJson.error(f"处理失败,请联系管理员![{str(e)}]"))

# 查询剪切任务列表
@subapp.route('/subtitle/getClipSubTaskList', methods=['GET', 'POST'])
@auth.require_auth 
def getClipSubTaskList():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')
    page = request.args.get('page', '1')  
    pagesize = request.args.get('pagesize', '12')  
    if(corpid == '' or corpid == None or userid == '' or userid == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata, totle = dbClipExecute.getClipSubTaskList(corpid, userid, page, pagesize)
    return jsonify(returnJson.success(ndata, tlen=totle))

@subapp.route('/subtitle/getClipSubTaskStatus', methods=['GET', 'POST'])
def getClipSubTaskStatus():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')  
    taskid = request.args.get('taskid')  
    if(id == '' or id == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata = dbClipExecute.getClipSubTaskStatus(corpid, userid, taskid)
    return jsonify(returnJson.success(ndata))

# 查询处理的日志
@subapp.route('/subtitle/getClipSubTaskLogs', methods=['GET', 'POST'])
@auth.require_auth 
def getClipSubTaskLogs():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')
    uuid1 = request.args.get('uuid1', '-1')  

    if(corpid == '' or corpid == None or userid == '' or userid == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata = dbClipExecute.getClipTaskLogs(uuid1)
    return jsonify(returnJson.success(ndata, tlen=1))

# 删除剪切任务
@subapp.route('/subtitle/delClipSubTask', methods=['GET', 'POST'])
def delClipSubTask():

    if request.method == 'POST':
       return jsonify(returnJson.error(msg=f"请使用GET方法提交;"))

    corpid = request.args.get('corpid')
    userid = request.args.get('uid')  
    taskid = request.args.get('taskid')  
    if(id == '' or id == None):
        return jsonify(returnJson.error(msg="接收前端数据错误"))
    # 根据用户和单位获取任务列表
    ndata = dbClipExecute.delClipSubTask(corpid, userid, taskid)
    return jsonify(returnJson.success1(None))

MONITOR_REDIS = os.environ.get('MONITOR_REDIS')
MONITOR_REDIS_PORT = int(os.environ.get('MONITOR_REDIS_PORT'))
# 增加GPU监控的功能
@subapp.route('/subtitle/getMonitorGpu', methods=['GET', 'POST'])
def getMonitorGpu():

    global ISMONITOR
    if ISMONITOR == False:
    # 开始线程监控
        thread = threading.Thread(target=monitor_gpus.monitor_gpus)
        thread.start()
        print("GPU监控线程启动")
        ISMONITOR = True

    # 对于小数据量，使用key*来进行
    r = redis.Redis(host=MONITOR_REDIS, port=MONITOR_REDIS_PORT, db=0)

    keys = r.keys("gpu_monitor:*")
    kdata = []
    for key in keys:
        value = r.get(key).decode('utf-8').replace("'","\"")
        value1 = key.decode('utf-8').split(":")
        mdata = {}
        mdata[value1[0]] = value1[1]
        mdata["data"] = json.loads(value)
        kdata.append(mdata)

    return jsonify(returnJson.success(kdata, tlen=len(kdata)))

# 获取任务状态，主要是给监控的使用
@subapp.route('/subtitle/taskStatus', methods=['GET', 'POST'])
def taskStatus():

    try:
        if request.method == 'POST':
            raise Exception(f"请使用GET方法提交;")

        corpid = request.args.get('corpid')
        userid = request.args.get('uid')
        result = {}
        ndata = dbExcute.getStatus(corpid)
        result["failed"] = ndata[0][0]
        result["completed"] = ndata[0][1]
        result["waitting"] = ndata[0][2]
        result["processing"] = ndata[0][3]
        return result
    except Exception as e:
        result = {}
        result["failed"] = 0
        result["completed"] = 0
        result["waitting"] = 0
        result["processing"] = 0
        return result

if __name__ == '__main__':
    serve(subapp, host='0.0.0.0', port=5003)